package de.hauck.rtmidlet;

import java.io.IOException;
import java.util.Calendar;
import java.util.Vector;

import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import de.hauck.rtmidlet.model.Configuration;
import de.hauck.rtmidlet.model.StockBean;
import de.hauck.rtmidlet.model.StockStore;
import de.hauck.rtmidlet.utils.MyLogger;
import de.hauck.rtmidlet.utils.Utils;
import de.hauck.rtmidlet.views.CanvasCharts;
import de.hauck.rtmidlet.views.CanvasDummy;
import de.hauck.rtmidlet.views.CanvasIB;
import de.hauck.rtmidlet.views.CanvasImage;
import de.hauck.rtmidlet.views.CanvasSearch;
import de.hauck.rtmidlet.views.CanvasSplash;
import de.hauck.rtmidlet.views.CanvasYahoo;
import de.hauck.rtmidlet.views.FormAdHoc;
import de.hauck.rtmidlet.views.FormSettingsMenu;


public class RTMidlet extends MIDlet implements CommandListener {

	// TODO: JavaDocs
	// TODO: Trace aktivieren
	// TODO: trace off closes log-stream to view in log-viewer
	// TODO: weitere mobile Links?
	// TODO: WebService Abfrage
	// TODO:
	// How_to_get_System.out_output_from_a_MIDlet_and_save_it_to_a_file_in_S60_devices
	// TODO: yahooBean / StockBean Abgleich / yahoo exceptions fangen
	// TODO: refresh imagePreviews FT / download all in eigenem thread & confirm
	// TODO: mobile finanz

	// TODO: eigene online bean mit name,url,image[],imagePrev[]
	// TODO: immer auf online-bean zugreifen
	// TODO: config & yahoo-zeit
	
	// TODO: IBCanvas only totals on last slide
	// TODO: separate monthly IBBeans on daily slides

	// TODO: Canvas for StartUp (menu & keypressed)
	
	private static RTMidlet _rtmidlet;
	//private MyLogger logger;

	private Command cGetChart = new Command("Chart", Command.BACK, 1);
	private Command cOverviewYahoo = new Command("Yahoo", Command.OK,
			1);
	private Command cChartOverview = new Command("Charts Overview", Command.OK, 3);
	private Command cSettings = new Command("Setup...", Command.OK, 4);
	private Command cLink1 = new Command("Link Finanztreff", Command.OK, 5);
	private Command cLink2 = new Command("Link OnVista", Command.OK, 6);
	private Command cLink3 = new Command("FT mobile", Command.OK, 7);
	private Command cLink4 = new Command("Intern. Broker", Command.OK, 8);
	private Command cAdHoc = new Command("AdHoc Query", Command.OK, 9);
	private Command cSearch = new Command("Search", Command.OK, 10);
	private Command cAbout = new Command("About", Command.OK, 11);
	
	private Command cExit = new Command("Exit", Command.EXIT, 1);
	private Command cExitYes = new Command("Yes", Command.OK, 1);
	private Command cExitNo = new Command("No", Command.BACK, 1);

	private int lastSelected = 0;
	private Display _display;
	private Displayable _current;
	private StockStore myStore;

	private FormSettingsMenu _settingsForm;

	private CanvasYahoo _yahooCanvas;
	private CanvasSearch _searchCanvas;
	private CanvasCharts _ftCanvas;
	private CanvasSplash _splashCanvas;
	private CanvasImage _imageCanvas;

	private List chartRTList;

	private Vector _filteredRTChartVec;

	public RTMidlet() {
		MyLogger.init();
		Configuration.VERSION=getAppProperty("MIDlet-Name")+" v"+getAppProperty("MIDlet-Version");
		Configuration.AUTHOR=getAppProperty("MIDlet-Vendor");
		//logger = MyLogger.getLogger();
		_rtmidlet = this;
	}

	public static RTMidlet getInstance() {
		return _rtmidlet;
	}

	protected void destroyApp(boolean arg0) {
		myStore.close();
	}

	protected void pauseApp() {
	}

	protected void startApp() throws MIDletStateChangeException {
		_splashCanvas = new CanvasSplash();
		_splashCanvas.show(false);
		_display = Display.getDisplay(this);
		_splashCanvas.showProgress("Loading Store...");
		myStore = new StockStore();
		MyLogger.info(Utils.convertCal2DateTimeStamp(Calendar.getInstance())
				+ " RTMidlet started");
		_splashCanvas.showProgress("Press a key");
	}

	void exitRequested() {
		MyLogger.info(Utils.convertCal2DateTimeStamp(Calendar.getInstance())
				+ " RTMidlet ended");
		destroyApp(false);
		notifyDestroyed();
	}

	public List getRTChartList() {
		_filteredRTChartVec = myStore
				.getFilteredStockVector(0);
		String[] menuElements = new String[_filteredRTChartVec.size()];
		for (int i = 0; i < _filteredRTChartVec.size(); i++) {
			menuElements[i] = ((StockBean) _filteredRTChartVec.elementAt(i))
					.getName();
		}

		chartRTList = new List("RT Charts", Choice.IMPLICIT, menuElements, null);
		if (chartRTList.size() <= lastSelected)
			chartRTList.setSelectedIndex(chartRTList.size() - 1, true);
		else
			chartRTList.setSelectedIndex(lastSelected, true);

		chartRTList.addCommand(cExit);
		chartRTList.addCommand(cGetChart);
		chartRTList.addCommand(cOverviewYahoo);
		//chartRTList.addCommand(cFinanztreff);
		chartRTList.addCommand(cChartOverview);
		if (null!=Configuration.link1 && !Configuration.link1.equals("")) chartRTList.addCommand(cLink1);
		if (null!=Configuration.link2 && !Configuration.link2.equals("")) chartRTList.addCommand(cLink2);
		if (null!=Configuration.urlIB && !Configuration.urlIB.equals("")) chartRTList.addCommand(cLink4);
		chartRTList.addCommand(cSettings);
		chartRTList.addCommand(cAbout);
		chartRTList.addCommand(cSearch);
		chartRTList.addCommand(cLink3);
		chartRTList.addCommand(cAdHoc);
		chartRTList.setSelectCommand(cGetChart);
		chartRTList.setCommandListener(this);
		return chartRTList;
	}

	public void commandAction(Command command, Displayable disp) {
		_current = Display.getDisplay(this).getCurrent();
		lastSelected = chartRTList.getSelectedIndex();
		if (command == cGetChart) {
			StockBean selStock = (StockBean) _filteredRTChartVec
					.elementAt(chartRTList.getSelectedIndex());

			String[][] urls = Configuration.getAvailableUrls(selStock);
			if (null!=urls && urls[0].length>0) {
				System.out.println("urlArraylength: "+urls[0].length);
				for (int i=0; i<urls[0].length; i++)  {
					System.out.println(i+" 0: "+urls[0][i]);
					System.out.println(i+" 1: "+urls[1][i]);
				}
				
				if (null == _imageCanvas)
					_imageCanvas = new CanvasImage(disp, urls);
				else
					_imageCanvas.setUrls(urls);
				_imageCanvas.downloadPic(selStock.getName(), 0);
				show(_imageCanvas);
			} else {
				this.alert("Info", "No symbol maintained for "
						+ selStock.getName(), Configuration.ALERT_WAIT_TIME);
				MyLogger.debug("No RT symbol maintained for "
						+ selStock.getName());
			}
		} else if (command == cExit) {
			Alert exit_alert = new Alert("Exit", "Do you really want to exit?",
					null, AlertType.CONFIRMATION);
			exit_alert.addCommand(cExitYes);
			exit_alert.addCommand(cExitNo);
			exit_alert.setCommandListener(this);
			exit_alert.setTimeout(5000);
			_display.setCurrent(exit_alert);
		} else if (command == cExitYes) {
			try {
				myStore.saveStocks();
				myStore.saveConfig();
				// logger.debug("stocks & config saved");
			} catch (IOException e) {
				MyLogger.error(e.getMessage());
				e.printStackTrace();
			}
			destroyApp(false);
			notifyDestroyed();
		} else if (command == cExitNo) {
			showMenu();
		} else if (command == cOverviewYahoo) {
			// must create new instance, maybe #-stocks changed
			_yahooCanvas = new CanvasYahoo(_display, _current, myStore
					.getFilteredStockVector(Configuration.FILTER_OVERVIEW_YAHOO), myStore);
			show(_yahooCanvas);
		} else if (command == cChartOverview) {
			// must create new instance, maybe #-stocks changed
			_ftCanvas = new CanvasCharts(0, _display, _current,
					myStore.getFilteredStockVector(0), myStore);
			show(_ftCanvas);
		} else if (command == cLink1) {
			try {
				this.platformRequest(Configuration.link1);
			} catch (ConnectionNotFoundException e) {
				e.printStackTrace();
			}
		} else if (command == cLink2) {
			try {
				this.platformRequest(Configuration.link2);
			} catch (ConnectionNotFoundException e) {
				e.printStackTrace();
			}
		} else if (command == cLink3) {
			CanvasDummy cd = new CanvasDummy(_current);
			_display.setCurrent(cd);
		} else if (command == cLink4) {
			CanvasIB cIB = new CanvasIB();
			_display.setCurrent(cIB);
			
		} else if (command == cAdHoc) {
			FormAdHoc formAdHoc = new FormAdHoc(this);
			show(formAdHoc);
		} else if (command == cSettings) {
			if (_settingsForm == null)
				_settingsForm = new FormSettingsMenu(_display, _current,
						myStore, this);
			else
				show(_settingsForm.getSettingsMenu()); 
		} else if (command == cAbout) {
			_splashCanvas.show(true);
		} else if (command == cSearch) {
			_searchCanvas = new CanvasSearch(_display, _current, myStore);
			show(_searchCanvas);
		}
	}


	public void show(Displayable d) {
		try {
			Display.getDisplay(this).setCurrent(d);
		} catch (IllegalArgumentException iae) {
			MyLogger.error("Could not display the new displayable " + d + ", "
					+ iae.getMessage());
		}
		/**
		 * Keep track of what the Midlet should be displaying. This is
		 * necessary, as a call to getDisplay following a setDisplay does not
		 * necessarily return the display just set, as the display actually gets
		 * set asynchronously. There also doesn't seem to be a way to find out
		 * what will be displayed next, or "serialise" on the setDisplay call.
		 * 
		 * This can cause problems, if an Alert is set just after a call to
		 * setDisplay. The call uses getDisplay to determine what to show after
		 * the Alert is dismissed, but the setDisplay might not have had an
		 * effect yet. Hence, keep manually track.
		 */
		_current = d;
		// shouldBeDisplaying = d;
	}

	public void showMenu() {
		show(getRTChartList());
	}

	public void alert(String title, String message, int timeout) {
		Alert alert = new Alert(title);
		alert.setTimeout(timeout);
		alert.setString(message);
		// #debug info
		// l.info("Showing Alert: " + message);
		try {
			if (_current == null)
				Display.getDisplay(this).setCurrent(alert);
			else
				Display.getDisplay(this).setCurrent(alert, _current);
		} catch (IllegalArgumentException iae) {
			/**
			 * Nokia S40 phones seem to throw an exception if one tries to set
			 * an Alert displayable when the current displayable is an alert
			 * too.
			 * 
			 * Not much we can do about this, other than just ignore the
			 * exception and not display the new alert.
			 */
			// l.info("Could not display this alert (" + message + "), " +
			// iae.getMessage());
		}
	}

	protected void keypressed(int key) {
		System.out.println(key);
	}

	public StockStore getStockStore() {
		return myStore;
	}

	public void setCurrent(Displayable current) {
		_current = current;
	}
}
